from logging.config import fileConfig

from pymongo import MongoClient
from pymongo.monitoring import CommandListener
import pandas as pd
import configparser
import numpy as np
import logging
import os


# https://mongokit.readthedocs.io/index.html
# https://pymongo.readthedocs.io/en/stable/index.html
# https://mongoz.tarsild.io/mongoz/
# https://github.com/Fig-Joaquin/CRUD-MongoDB-Python3/tree/master/src
# https://github.com/Riofuad/Flask-Web-MongoDB/blob/main/app.py
# https://github.com/blackwakhu/python-phonebook-mongodb/blob/main/functions.py
# https://gurcuff91.github.io/mongotoy/docs/database/

cfgdir = os.path.split(os.path.realpath(__file__))[0]
paths = cfgdir.split("/")
a = len(paths)-1
separator = '/'
arr = paths[1:a]
b = '/'+separator.join(arr)+'/'
cfg = os.path.join(cfgdir,'logging_config.ini')
fileConfig(b+"logging_config.ini", disable_existing_loggers=False)
logger = logging.getLogger('simple_example')

class CommandLogger(CommandListener):
    def started(self, event):
        logger.info(f"Command started: {event.command}")

    def succeeded(self, event):
        logger.info(f"Command succeeded: {event.reply}")

    def failed(self, event):
        logger.info(f"Command failed: {event.command}")

class MongoHelper(object):
    def __init__(self, database, collection=None, host="127.0.0.1", port=27017, url=None):
        # print(url, database)
        self.mongo_conn = None
        if url:
            # print(" url is not none")
            self.mongo_conn = MongoClient(host=url)
        else:
            # print(" url is none")
            self.mongo_conn = MongoClient(host=host, port=port)
            self.mongo_conn.register_listener(CommandLogger())
        self.mongo_db = self.mongo_conn.get_database(database)  # 数据库连接（pymongo自带连接池）
        self.coll = None
        if collection:  # 集合
            self.coll = self.mongo_db.get_collection(collection)

    def set_collection(self, collection):
        """指定链接的集合"""
        self.coll = self.mongo_db.get_collection(collection)
        print(self.coll.find_one())

    def get_coll(self):
        return self.coll

    def _save_or_update_mongodb(self, record, dict_value, drop=False):
        """根据检查_id，如果存在就覆盖，如果不存在就新增
        :param record: 数据库记录
        :param dict_value: 待保存的数据
        :param drop: 如果有记录，是否先删除后保存
        """
        if not record:  # 不存在，直接插入
            self.coll.insert_one(dict_value)
        elif drop is True:  # 先删除，然后插入，相当于覆盖原始数据
            self.coll.delete_one(record)
            self.coll.insert_one(dict_value)
        else:  # 更新
            self.coll.update_one(record, {
                "$set": dict_value,
            })

    def get_all_data(self, record_list=["_id"]):
        """获取全部数据，record_list中为需要的数据列名称"""
        for _record in self.coll.find({}, record_list):
            yield _record

    def save_new_dataframe_to_mongo(self, dataframe: pd.DataFrame):
        """保存dataframe格式的新数据到MongoDB，会自动分配_id，也可以指定_id"""
        coll = self.get_coll()
        coll.insert_many(dataframe.to_dict(orient="record"))

    def update_dataframe(self, dataframe: pd.DataFrame, record_by: list = ["_id"], drop=False):
        """多线程插入dataframe"""
        import threading
        coll = self.get_coll()
        # 剔除dataframe中不存在的列名
        record_by = [_r for _r in record_by if _r in dataframe.columns]
        thread_list = []
        for df_record in dataframe.to_dict(orient="record"):
            find_dict = {}
            for _r_by in record_by:
                find_dict[_r_by] = df_record[_r_by]
            record = coll.find_one(find_dict, {})
            thread = threading.Thread(target=self._save_or_update_mongodb, args=(record, df_record, drop))
            thread.start()
            thread_list.append(thread)
        for _thr in thread_list:  # 等待线程全部执行完毕
            _thr.join()

    def update_dict(self, new_dict_value: dict, record_by: list = ["_id"], drop=False):
        """更新一个dict的数据"""
        coll = self.get_coll()
        record_by = [_r for _r in record_by if _r in new_dict_value.keys()]
        find_dict = {}
        for _r_by in record_by:
            find_dict[_r_by] = new_dict_value[_r_by]
        record = coll.find_one(find_dict, {})
        self._save_or_update_mongodb(record, new_dict_value, drop=drop)

def main( url, database):
    # print(url, database)
    mongo_helper = MongoHelper(url=url, database=database)
    mongo_helper.set_collection("test")
if __name__ == '__main__':
    config = configparser.ConfigParser()
    config.read('../config.cfg')
    config.get('db', 'host')
    database = config.get('db', 'database')
    config.get('db', 'port')
    config.get('db', 'username')
    config.get('db', 'password')
    myUrl = config.get('db', 'url')
    # print(database)
    main(url=myUrl, database=database)
